/***************************************************************************
 *   This is a part of the NextCAD Web APP.                                *
 *   Copyright (C) AMCAX, All rights reserved.                             *
 ***************************************************************************/
import {
  BaseCommand,
  CENTEREVENTS,
  EventsRes,
  ICmdDialogParams,
  ICurve,
  MessageTip,
} from '@amcax/base';

import i18n from 'i18next';
import { useEffect, useRef, useState } from 'react';

import CircleCmdInteractor from './CmdInteractor';
import ThreePointCircleCmdInteractorTwo from './three-point-circle';
import { useMutiPick2D } from '@app-base/common/components/pick-input/2d';
import { useCommand } from '@app-base/common/hooks/useCommand';
import { wsApi } from '@app-base/server';
import { Vector3 } from 'three-legacy';
import { isParallel, renderSketch } from '@app-base/common/utils';
import { sketchEventCenter } from '@app-base/environments/nextcad/events/SketchEventCenter';

function CircleCommand({ onClose }: ICmdDialogParams) {
  const cmdRef = useRef<CircleCmdInteractor>(null);
  useEffect(() => {
    cmdRef.current = new CircleCmdInteractor();
    cmdRef.current.addExit(onClose);
    return () => {
      cmdRef.current?.destroy();
      cmdRef.current = null;
    };
  }, []);
  return <></>;
}

export const cmdCircle: BaseCommand = {
  id: 'CmdCircle',
  label: 'command.circle',
  icon: 'commands/sketch/circle',
  group: 'sketch',
  create: function (label: string, onClose: () => void) {
    return (
      <CircleCommand
        title={i18n.t(label)}
        onClose={onClose}
      />
    );
  },
};

function ThreePointCircleCommand({ onClose }: ICmdDialogParams) {
  const cmdRef = useRef<ThreePointCircleCmdInteractorTwo>(null);
  useEffect(() => {
    cmdRef.current = new ThreePointCircleCmdInteractorTwo();
    cmdRef.current.addExit(onClose);
    return () => {
      cmdRef.current?.destroy();
      cmdRef.current = null;
    };
  }, []);
  return <></>;
}

export const cmdThreePointCircle: BaseCommand = {
  id: 'cmdThreePointCircle',
  label: 'command.three-point-circle',
  icon: 'commands/sketch/three-point-circle',
  group: 'sketch',
  create: function (label: string, onClose: () => void) {
    return (
      <ThreePointCircleCommand
        title={i18n.t(label)}
        onClose={onClose}
      />
    );
  },
};

function ThreeLineCircleCommand({ onClose }: ICmdDialogParams) {
  const [selectedLines, setSelectedLines] = useState<ICurve[]>([]);

  useCommand('sketch-3line-circle', {
    onClose,
  });

  const { register, unRegister } = useMutiPick2D({
    onPick: (_, curves) => {
      if (curves.length > 3) {
        return;
      }
      setSelectedLines(curves.filter((c) => c.type !== 'Point'));
    },
    value: selectedLines.map((c) => c.id),
    controlled: true,
    isMulti: true,
    allowMarqueeSelect: false,
  });

  useEffect(() => {
    if (selectedLines.length === 3) {
      const [line1Points, line2Points, line3Points] = selectedLines.map(
        (s) =>
          new Vector3(
            s.vertices[1][0] - s.vertices[0][0],
            s.vertices[1][1] - s.vertices[0][1],
          ),
      );

      if (
        selectedLines.every((l) => l.type === 'Line') &&
        isParallel(line1Points, line2Points) &&
        isParallel(line2Points, line3Points)
      ) {
        MessageTip.warning('三条平行线无法创建圆');
      } else {
        (async () => {
          const sketchId = sketchEventCenter().getSketchInfo().sketchId;
          const result = await wsApi.createSketchCircle3Curves(
            sketchId,
            selectedLines.map((v) => v.id),
          );

          renderSketch(sketchId, result);

          setSelectedLines([]);
        })();
      }
    }
  }, [selectedLines]);

  useEffect(() => {
    register();

    const onPointerUp = (e: EventsRes<PointerEvent>) => {
      if (e.button.onRight) {
        setSelectedLines([]);
      }
    };

    sketchEventCenter().on(CENTEREVENTS.POINTERUP, onPointerUp);
    return () => {
      unRegister();
      sketchEventCenter().off(CENTEREVENTS.POINTERUP, onPointerUp);
    };
  }, []);

  return <></>;
}

export const cmdThreeLineCircle: BaseCommand = {
  id: 'cmdThreeLineCircle',
  label: 'command.sketch-cmds.three-line-circle',
  icon: 'commands/sketch/three-line-circle',
  group: 'sketch',
  create: function (label: string, onClose: () => void) {
    return (
      <ThreeLineCircleCommand
        title={i18n.t(label)}
        onClose={onClose}
      />
    );
  },
};
